/* 
 * @(#)AnimalBean.java 
 *  
 * Esta clase presenta la informacion de un animal especifico.  
 * 
 * @version 1.0
 * @date 01/11/12 
 * @author Karen Calderón 
 *  
 */
package muhnes.sizoo.controlador;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.event.ActionEvent;
import javax.faces.model.SelectItem;
import muhnes.sizoo.dal.AnimalDao;
import muhnes.sizoo.dal.EspecieDao;
import muhnes.sizoo.dal.EtiquetaDao;
import muhnes.sizoo.dal.FabricaDAO;
import muhnes.sizoo.dal.GrupoDao;
import muhnes.sizoo.dal.InternacionalDao;
import muhnes.sizoo.dal.NacionalDao;
import muhnes.sizoo.dal.ResenyaDao;
import muhnes.sizoo.modelo.*;
import muhnes.sizoo.util.Transaccion;
import org.primefaces.event.FlowEvent;
import org.primefaces.event.map.OverlaySelectEvent;
import org.primefaces.model.map.DefaultMapModel;
import org.primefaces.model.map.LatLng;
import org.primefaces.model.map.MapModel;
import org.primefaces.model.map.Marker;


/**
 * 
 * Clase controladora que da mantenimiento a la vista animal incluyendo 
 * la sinonimia y la reseña que son propias del animal
 * @author Karen Calderon
 */
@ManagedBean(name = "animalBean")
@ViewScoped
public class AnimalBean extends CRUDBean< Animal, AnimalDao > 
    implements Serializable{
    
    private Animal animalSeleccionado;
    private Resenya resenya;
    private Sinonimia sinonimia;
    private List< Sinonimia > listaSinonimias;
    private List < Etiqueta > listaEtiquetas;
    private List< SelectItem > itemsEspecie;
    private List< SelectItem > itemsFotos;
    private List< String> etiquetasSeleccionadas;
    private MapModel mapa; 
    private String OPCION;
    private String etiqueta;
    private char valores = 'N';
    private String aux;
    
    private List< SelectItem > itemsGrupos;
    
    /** Crea una nueva instancia de AnimalBean */
    public AnimalBean() {
        super( Animal.class );
        vistaProtegida = "animal";
        resenya = new Resenya();
        sinonimia = new Sinonimia();
        mapa = new DefaultMapModel();
    }
    
    /**
     * Metodo para obtener todos los grupos 
     * @return devuelve un objeto de tipo list que contiene todos los items
     */
     public List< SelectItem > getItemsGrupos() {
        if( itemsGrupos == null ) {
            itemsGrupos = new ArrayList< SelectItem >();
            GrupoDao grupoDao = FabricaDAO.crearGrupoDao();
            for( Grupo grupo : grupoDao.buscarTodos() ) {
                Grupo g = grupoDao.removerProxy(grupo);
                SelectItem item = new SelectItem( g, g.getNombre() );
                itemsGrupos.add( item );
            }
        }
        return itemsGrupos;
    }
    
    /**
     * metodo para obtener el valor de la resenya
     * @return devuelve una entidad de tipo resenya
     */
    public Resenya getResenya(){
        return resenya;
    }
    
    /**
     * Metodo para asignar el valor de la resenya
     * @param resenya de tipo resenya 
     */
    public void setResenya (Resenya resenya){
        this.resenya = resenya;
    }
    
    /**
     * Metodo para obtener el valor de la sinonimia
     * @return Sinonimia de tipo sinonimia
     */
    public Sinonimia getSinonimia() {
        return sinonimia;
    }

    /**
     * Asigna el valor de la sinonimia a usar
     * @param sinonimia de tipo Sinonimia
     */
    public void setSinonimia(Sinonimia sinonimia) {
        this.sinonimia = sinonimia;
    }
    
    /**
     * Metodo para obtener las opciones
     * @return
     */
    public String getOpcion(){
        return OPCION;
    }
    
    /**
     * Metodo para asignar la opcion
     * @param opcion
     */
    public void setOpcion(String opcion){
        this.OPCION = opcion;
    }
   
    /**
     * Metodo para obtener las etiquetas
     * @return
     */
    public String getEtiqueta(){
        return etiqueta;
    }
    
    /**
     * metodo para asignar las etiquetas
     * @param etiqueta
     */
    public void setEtiqueta(String etiqueta){
        this.etiqueta = etiqueta;
    }
    
    /**
     * Metodo que prepara el animal que se agregara
     * @param event de tipo ActionEvent
     */
    @Override
    public void prepararAdicion( ActionEvent event  ){
        entidad = new Animal();
        etiquetasSeleccionadas = null;
    }
    
    /**
     * Metodo para prepara la modificaciones que se haran al animal
     * @param animal de tipo animal que indica el animal que sera modificado
     */
    @Override
    public void prepararModificacion( Animal animal ){
        this.entidad = animal;
        etiquetasSeleccionadas = null;
    }
    
    /**
     * Metodo para preparar la resenya del animal, indica si la resenya actual
     * sera una modificacion o una insercion
     * 
     * @param animal de tipo Animal
     */
    public void prepararResenya( Animal animal ){
            this.entidad = animal;
            try{
                System.out.println("entro pero ignoro el cathc");
                ResenyaDao resenyaDao = FabricaDAO.crearResenyaDao();

                resenya = resenyaDao.buscarPorAnimal(animal.getCodigoanimal());

                if (resenya == null){
                    OPCION = "INSERCION";    
                    resenya = new Resenya();
                } else {
                    OPCION = "ACTUALIZACION";
                    resenya.setContenidoanterior(resenya.getContenidoactual());
                }
            }
            catch(java.lang.NullPointerException e)
            { 
                System.out.println(" del arreglo esta vacia 12");
            }
                   
                    
       
        
    }
    
    /**
     * Metodo que carga el animal del cual se obtendran las coordenas
     * 
     * @param animal 
     */
    public void prepararMapa( Animal animal ) {
        mapa = new DefaultMapModel();
            AnimalDao animalDao = FabricaDAO.crearAnimalDao();
        List<Recoleccion> listaCoordenadas = 
                animalDao.buscarRecoleccionesAsociadas(animal);
        for(Recoleccion recoleccion : listaCoordenadas) {   
            String lugar; 
            int codigo = recoleccion.getCodigorecoleccion();
            if( recoleccion.getTiporecoleccion() == 'N' ) {
                NacionalDao nacionalDao = FabricaDAO.crearNacionalDao();
                Nacional nacional = nacionalDao.buscarPorId( codigo );
                lugar = nacional.getZona().getUbicacion();
            }
            else {
                InternacionalDao internacionalDao = FabricaDAO.crearInternacionalDao();
                Internacional internacional = internacionalDao.buscarPorId( codigo );
                lugar = internacional.getPais();
            }
            
            Especimen e = null;
            for( Especimen es : recoleccion.getEspecimenes() ) {
                if( es.getAnimal().getCodigoanimal() == animal.getCodigoanimal() ) {
                    e = es;
                    break;
                }
            }
                                                             
            mapa.addOverlay(
                new Marker(new LatLng(
                    recoleccion.getLatitud().doubleValue(), 
                    recoleccion.getLongitud().doubleValue()), 
                    lugar, 
                    e));
        }
    }
    
    private Marker marcador;
    
    public Marker getMarcador(){
        return marcador;
    }
    
    /**
     * MEtodo para seleccionar el lugar que quiere ver en la
     * lista de especimenes que se muestra en el mapa
     * @param evento
     */
    public void seleccionarMarcador(OverlaySelectEvent evento) {  
        marcador = (Marker) evento.getOverlay();  
    }
    
    /**
     * Metodo para obtener el especimen marcador 
     * @return 
     */
    public Especimen getEspecimenMarcador() {
        return (Especimen)marcador.getData();
    }
     
    /**
     * Metodo encargado para manejo de las etiquetas
     * del animal que se esta actualizando
     * @return 
     */
    private Set<Etiqueta> actualizarEtiquetas() {
        System.out.print(entidad.getFotos());
        Set<Etiqueta> etiquetas = new HashSet<Etiqueta>();
        for( String etiquet : getEtiquetasSeleccionadas() ) {
            Etiqueta etiquetax = new Etiqueta();
            etiquetax.setNombre(etiquet);
            EtiquetaDao dao = FabricaDAO.crearEtiquetaDao();
            if( dao.verificarUnicidad(etiquetax) ) {
                etiquetax = dao.buscarPorNombre(etiquet);
                etiquetas.add(etiquetax);
            }
            else {
                dao.guardar(etiquetax);
                etiquetax = dao.buscarPorNombre(etiquet);
                etiquetas.add(etiquetax);
            }
        }
        
        return etiquetas;
    }
    
    /**
     * Metodo para insertar una etiqueta de un animal especifico.
     * @param event
     */
    @Override
    public void agregarEntidad( ActionEvent event ){
        
        AnimalDao animalDao = FabricaDAO.crearAnimalDao();
        
        boolean revisador = sesionBean.verificarPermiso("revisar", "animal");
        if ( valores == 'S' ) 
        {
            
        entidad.setEtiquetas(actualizarEtiquetas());
        }
        else if (valores == 'N'){
            
        entidad.setEtiquetas(null);    
        }
        entidad.setEstado( revisador ? "Activo" : "Revision" );
        animalDao.guardar( entidad );
        
        recrearModelo();
    }
    
    /**
     * Metodo para actualizar el animal
     * @param event
     */
    @Override
    public void actualizarEntidad( ActionEvent event ){
        AnimalDao animalDao = FabricaDAO.crearAnimalDao();
        
        if ( valores == 'S' ) 
        {
            
        entidad.setEtiquetas(actualizarEtiquetas());
        }
        else if (valores == 'N'){
            
        }
        animalDao.actualizar( entidad );
        recrearModelo();
    }
    
    /**
     * Metodo para eliminar un animal
     * @param event
     */
    @Override
    public void eliminarEntidad(  ActionEvent event ){
        if( !validarDependencia() ) {
            return;
        }
        
        AnimalDao animalDao = FabricaDAO.crearAnimalDao();
        entidad.setEstado("Deshabilitado");
        animalDao.actualizar( entidad );
        recrearModelo();
    }

    /**
     * Metodo que indica si se actualizara o agregara la resenya
     * @param event
     */
    public void guardarResenya( ActionEvent event ){
      
        if( OPCION.equals("INSERCION")) {
            agregarResenya( event );
        }
        else if( OPCION.equals("ACTUALIZACION")) {
            actualizarResenya( event );
        }
        else {
            OPCION = "NINGUNA";
        }
               
    }
    
    /**
     * Metodo para agregar las resenyas
     * @param event
     */
    public void agregarResenya( ActionEvent event ){
        
        if( resenya.getContenidoactual().length() > 5000 ) {
            String contenido = resenya.getContenidoactual().substring( 0, 4999);
            resenya.setContenidoactual( contenido );
        }
       
        ResenyaDao resenyaDao = FabricaDAO.crearResenyaDao();
        resenya.setAnimal(entidad);
        resenya.setEstado("Activo");
        resenya.setAutor( sesionBean.getUsuario().getNombre() );
        resenya.setFechacreacion( Calendar.getInstance().getTime() );
        resenyaDao.guardar( resenya );
        recrearModelo();
                  
    }
    
    /**
     * Metodo para actualizar la resenya
     * @param event
     */
    public void actualizarResenya (ActionEvent event){
        
        if( resenya.getContenidoactual().length() > 5000 ) {
            String contenido = resenya.getContenidoactual().substring( 0, 4999);
            resenya.setContenidoactual( contenido );
        }
        
        ResenyaDao resenyaDao = FabricaDAO.crearResenyaDao();
        resenya.setAutor( sesionBean.getUsuario().getNombre() );
        resenya.setFechamodificacion( Calendar.getInstance().getTime() );
        resenyaDao.actualizar(resenya);
       
    }
        
    /**
     * Listas las especies
     * @return un objeto de listas de todas las especies
     */
    public List< SelectItem > getItemsEspecie() {
        if( itemsEspecie == null ) {
            itemsEspecie = new ArrayList< SelectItem >();
            EspecieDao especieDao = FabricaDAO.crearEspecieDao();
            for( Especie especie : especieDao.buscarTodos() ) {
                Especie e = especieDao.removerProxy(especie);
                SelectItem item = new SelectItem( e, e.getNombre());
                
                itemsEspecie.add( item );
            }
        }
        return itemsEspecie;
    }
    
    /**Metodo para obtener las etiquetas del animal seleccionado
     * 
     * @return
     */
    public List<Etiqueta> getEtiquetasAnimal() {
        List<Etiqueta> etiquetasAnimal = new ArrayList<Etiqueta>();
        for( Etiqueta etiquetaA : entidad.getEtiquetas()) {
            etiquetasAnimal.add( etiquetaA );
        }
        return etiquetasAnimal;
    }
        
    /**
     * Metodo para setear la lista de etiquetas
     * @param etiquetas
     */
    public void setEtiquetasAnimal( List<Etiqueta> etiquetas ) {
        Set<Etiqueta> etiquetasAnimal = new HashSet<Etiqueta>();
        for( Etiqueta etiquetaA : etiquetas ) {
            etiquetasAnimal.add( etiquetaA );
        }
        entidad.setEtiquetas(etiquetasAnimal);
    }

    /**
     * Metodo para listar las etiquetas que estan agregadas al sistema
     * @return
     */
    public List< Etiqueta > getListaEtiquetas() {
        if( listaEtiquetas == null ) {
            EtiquetaDao dao = FabricaDAO.crearEtiquetaDao();
            listaEtiquetas = dao.buscarTodos();
        }
        return listaEtiquetas;
    }
   
    /**
     * Metodo que indica si el flujo se puede o no continuar
     * @param event
     * @return
     */
    public String procesarFlujoAdicion( FlowEvent event ) {  
        return event.getNewStep();  
    }  
    
    /**
     * Metodo para listar las sinonimias de un animal
     * @param anim de tipo animal al cual se le obtendras las sinonimias
     * @return
     */
    public List< Sinonimia > getSinonimias(  Animal anim ) {
        List< Sinonimia > sinonimias = new ArrayList< Sinonimia >();
        for( Sinonimia sinonimi : anim.getSinonimias() ) {
           sinonimias.add(sinonimi); 
        }
        return sinonimias;
    }
    
    /**
     * metodo para obtener el animal seleccionado
     * @return
     */
    public Animal getAnimalSeleccionado() {
        return animalSeleccionado;
    }

    /**
     * MEtodo para asignar el valor al animal
     * @param animalSeleccionado
     */
    public void setAnimalSeleccionado(Animal animalSeleccionado) {
        this.animalSeleccionado = animalSeleccionado;
    }
    
    /**
     * Metodo para listar las etiquetas
     * @return
     */
    public List< String> getEtiquetasSeleccionadas() {
       
        if( etiquetasSeleccionadas == null ) {
            etiquetasSeleccionadas = new ArrayList<String>();
        }
        
        if( etiquetasSeleccionadas.isEmpty() && entidad != null ) {
            for( Etiqueta etiquet : entidad.getEtiquetas() ) {
                etiquetasSeleccionadas.add(etiquet.getNombre());
            }
        }
        
        return etiquetasSeleccionadas;
    }
    
    /**
     * Metodo para agregar etiquetas 
     * @param evento
     */
    public void agregarEtiqueta(ActionEvent evento) {
         this.valores = 'S';
        if( !etiquetasSeleccionadas.contains(etiqueta) ) {
            etiquetasSeleccionadas.add(etiqueta);
        }
        etiqueta = null;
    }
    
    /**
     * Metodo para eliminar las etiquetas 
     * @param etiquet
     */
    public void eliminarEtiqueta(String etiquet) {
        if( etiquetasSeleccionadas.contains(etiqueta) ) {
            etiquetasSeleccionadas.remove(etiquet);
        }
    }
    
    /**
     * Metodo que devuelve el objeto ma`pa con todas las coordenadas que tiene
     * @return
     */
    public MapModel getMapa() {
        return mapa;
    }
    
    /**
     * Metodo que presenta el mapa y ubicaciones de los especimenes
     * @return
     */
    public MapModel coordenadasMapa(){
        AnimalDao animalDao = FabricaDAO.crearAnimalDao();
        List<Recoleccion> listaCoordenadas = 
                animalDao.buscarRecoleccionesAsociadas(entidad);
        for(Recoleccion recoleccion : listaCoordenadas) {   
            String lugar = recoleccion.getTiporecoleccion() == 'N' ? 
                    ((Nacional)recoleccion).getZona().getUbicacion() :
                    ((Internacional)recoleccion).getPais();
            List<Especimen> especimenes = animalDao.buscarFotoRecoleccion(entidad, recoleccion);
            int indice = (int)(Math.random() * ( especimenes.size() - 1 ));
            this.aux = especimenes.get( indice ).getCodigoespecimen();
            
            mapa.addOverlay(
                new Marker(new LatLng(
                    recoleccion.getLatitud().doubleValue(), 
                    recoleccion.getLongitud().doubleValue()), 
                    lugar,this.aux));
        }
        
        return mapa;
    }

    /**
     * Metodo para instanciar la interfaz dao de animal
     * @return
     */
    @Override
    protected AnimalDao getDAO () {
        return FabricaDAO.crearAnimalDao();
    }

    /**
     * 
     * @param transaccion indica que transaccion se debera realizar 
     * @return objeto de tipo boolean que indica que tipo de transaccion se reallizara
     */
    @Override
    protected boolean debeValidar (Transaccion transaccion) {
        boolean validacion = false;
        
        switch( transaccion ) {
            case INSERCION:
            case ACTUALIZACION:
            case ELIMINACION:
                validacion = true;
        }
        
        return validacion;
    }

    /**
     * Obtiene el valor 
     * @return
     */
    public char getValores() {
        return valores;
    }

    /**
     * Asigna el valor a la variable
     * @param valores
     */
    public void setValores(char valores) {
        this.valores = valores;
    }

    /**
     * Obtiene el valor de la variable auxiliar
     * @return
     */
    public String getAux() {
        return aux;
    }

    /**
     * Asigna una variable a aux que es una variable auxiliar 
     * @param aux
     */
    public void setAux(String aux) {
        this.aux = aux;
    }
    
   
}

